package com.webc.framework.start;

import com.webc.framework.config.Resource;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * @author hejianglong
 * @date 2018/9/6.
 */
public class LaunchClassloader {

    private static List<Class<?>> classes = null;

    public static List<Class<?>> getClasses() {
        if (classes == null) {
            loadClasses();
        }
        return classes;
    }

    public static Class<?> loadClass(String className, boolean isInitialized) {
        Class<?> clazz = null;
        try {
            clazz = Class.forName(className, isInitialized, getClassLoader());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return clazz;
    }

    public static List<Class<?>> loadClasses() {
        String baseScanPackage = "";
        try {
            if (classes == null) {
                baseScanPackage = getBaseScanPackage();
                classes = getClasses(baseScanPackage);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return classes;
    }

    private static String getBaseScanPackage() throws IOException {
        return Resource.getBaseScanPackage();
    }

    private static List<Class<?>> getClasses(String packageName) throws IOException {
        List<Class<?>> classes = new ArrayList<Class<?>>();
        String pkName = packageName.replace(".", "/");
        Enumeration<URL> urls = getClassLoader().getResources(pkName);
        while (urls.hasMoreElements()) {
            URL url = urls.nextElement();
            if (url != null) {
                String protocol = url.getProtocol();
                if (!"file".equals(protocol)) {
                    break;
                }
                // 转换空格
                String packagePath = url.getPath().replaceAll("%20", " ");
                addClasses(classes, packagePath, packageName);
            }
        }
        return classes;
    }

    private static ClassLoader getClassLoader() {
        return Thread.currentThread().getContextClassLoader();
    }

    private static void addClasses(List<Class<?>> classes, String packagePath, String packageName) {
        File[] files = new File(packagePath).listFiles();
        for(File file: files) {
            String fileName = file.getName();
            if (file.isFile()) {
                String className = packageName + "." + fileName.substring(0, fileName.lastIndexOf("."));
                classes.add(loadClass(className, false));
            } else {
                String subPackagePath = packagePath + "/" + fileName;
                String subPackageName = packageName + "." + fileName;
                addClasses(classes, subPackagePath, subPackageName);
            }
        }
    }
}
